<script setup>
import dayjs from 'dayjs';

import SsoUser from '@core/engine/ThirdPlatform/SsoUser';
import SsoRole from '@core/engine/ThirdPlatform/SsoRole';
import SubViewContainer from '@core/components/subLayout/SubViewContainer.vue';
import TableWithPagination from '@core/components/TableWithPagination.vue';

const { t } = useI18n({ inheritLocale: true, useScope: 'local' });

const isTableLoading = ref(true);

const authRoles = ref([]);
const users = ref([]);
const refreshUsers = async () => {
  isTableLoading.value = true;
  try {
    authRoles.value = await SsoRole.fetchList();
    // TODO: remove mocked auth roles
    const remoteUsers = await SsoUser.fetchList();
    users.value = remoteUsers.map((user) => {
      return {
        ...user,
        authRoles: [authRoles.value[Math.floor(Math.random() * 100) % 3]],
      };
    });
  } finally {
    isTableLoading.value = false;
  }
};
refreshUsers();

const editUserFormRef = ref();
const emptyUser = {
  userId: '',
  userName: '',
  authRoles: [],
  initialPassword: '',
  newPassword: '',
};
const editingUser = reactive({ ...emptyUser });
const editUserRules = {
  userName: [{ required: true, message: t('inputUserNamePlease'), trigger: 'blur' }],
  password: [{ required: true, message: t('inputPasswordPlease'), trigger: 'blur' }],
};
const DialogMode = {
  Creating: 'creating',
  Editing: 'editing',
  ResetPassword: 'resetPassword',
};
const isEditDialogShown = ref(false);
const isEditionSubmitting = ref(false);
const dialogMode = ref(DialogMode.Creating);
const onSubmitUser = async (formRef) => {
  if (!formRef) { return; }
  isEditionSubmitting.value = true;
  await formRef.validate();
  try {
    switch (dialogMode.value) {
      case DialogMode.ResetPassword: {
        const { userId, newPassword } = editingUser;
        await SsoUser.resetPasswordOf({ userId, password: newPassword });
        break;
      }
      case DialogMode.Editing:
        await SsoUser.updateOne(editingUser); break;
      case DialogMode.Creating: {
        const { initialPassword } = editingUser;
        await SsoUser.createOne({ ...editingUser, password: initialPassword });
        break;
      }
      default: break;
    }
  } finally {
    isEditionSubmitting.value = false;
    isEditDialogShown.value = false;
  }
  await refreshUsers();
};
const showDialog = () => {
  isEditDialogShown.value = true;
  editUserFormRef?.value.clearValidate();
};
const onClickAddUser = () => {
  Object.assign(editingUser, emptyUser);
  dialogMode.value = DialogMode.Creating;
  showDialog();
};
const onClickEditUser = (row) => {
  Object.assign(editingUser, row);
  dialogMode.value = DialogMode.Editing;
  showDialog();
};
const onClickResetUserPassword = (row) => {
  Object.assign(editingUser, row, { newPassword: '' });
  dialogMode.value = DialogMode.ResetPassword;
  showDialog();
};
const onDeleteUser = async (params) => {
  isTableLoading.value = true;
  try {
    await SsoUser.deleteOne(params.userId);
    await refreshUsers();
  } finally {
    isTableLoading.value = false;
  }
};
</script>

<template>
  <SubViewContainer>
    <template #header-suffix>
      <ElButton type="primary" @click="onClickAddUser">{{t('createUser')}}</ElButton>
    </template>
    <ElCard>
      <TableWithPagination
        v-loading="isTableLoading"
        :data="users"
        paginationLayout="sizes, total, prev, pager, next"
        :paginationTotal="users.length"
      >
        <ElTableColumn prop="userId" :label="t('id')" width="196" />
        <ElTableColumn prop="userName" :label="t('userName')" />
        <ElTableColumn :label="t('authRoles')">
          <template #default="{ row }">
            <ElTag
              v-for="authRole in row.authRoles"
              :key="authRole.roleId"
            >
              {{authRole.roleName}}
            </ElTag>
          </template>
        </ElTableColumn>
        <ElTableColumn :label="t('createdAt')">
          <template #default="{ row }">
            {{dayjs(row.createTime).format(t('datetimeFormatter'))}}
          </template>
        </ElTableColumn>
        <ElTableColumn :label="t('operations')" fixed="right">
          <template #default="{ row }">
            <ElLink type="primary" @click="onClickEditUser(row)">{{t('edit')}}</ElLink>
            <ElDivider class="divider" direction="vertical" />
            <ElLink type="primary" @click="onClickEditUser(row)">{{t('authRole')}}</ElLink>
            <ElDivider class="divider" direction="vertical" />
            <ElLink type="primary" @click="onClickResetUserPassword(row)">{{t('resetPassword')}}</ElLink>
            <ElDivider class="divider" direction="vertical" />
            <ElPopconfirm
              :title="t('sureToDelete', { userName: row.userName })"
              :width="226 + row.userName.length * 8"
              @confirm="onDeleteUser(row)"
            >
              <template #reference>
                <ElLink type="danger">{{t('delete')}}</ElLink>
              </template>
            </ElPopconfirm>
          </template>
        </ElTableColumn>
      </TableWithPagination>
    </ElCard>
    <ElDialog
      v-model="isEditDialogShown"
      :title="t(`dialogTitle.${dialogMode}`)"
      width="35%"
    >
      <ElForm
        ref="editUserFormRef"
        :rules="editUserRules"
        :model="editingUser"
        label-position="right"
        label-width="78px"
        class="edit-user-form"
      >
        <ElFormItem :label="t('id')">
          <ElInput
            v-model="editingUser.userId"
            :disabled="[DialogMode.Editing, DialogMode.ResetPassword].includes(dialogMode)"
          />
        </ElFormItem>
        <ElFormItem :label="t('userName')" prop="userName">
          <ElInput v-model="editingUser.userName" :disabled="dialogMode === DialogMode.ResetPassword" />
        </ElFormItem>
        <ElFormItem v-if="DialogMode.ResetPassword !== dialogMode" :label="t('authRoles')" prop="authRoles">
          <ElSelect
            v-model="editingUser.authRoles"
            value-key="roleId"
            filterable
            default-first-option
            multiple
            :placeholder="t('selectRolesPlease')"
            class="roles-selector"
          >
            <ElOption
              v-for="role in authRoles"
              :key="role.roleId"
              :label="role.roleName"
              :value="role"
            />
          </ElSelect>
        </ElFormItem>
        <ElFormItem v-if="dialogMode === DialogMode.ResetPassword" :label="t('newPassword')">
          <ElInput
            v-model="editingUser.newPassword"
            type="password"
            show-password
          />
        </ElFormItem>
        <ElFormItem v-if="dialogMode === DialogMode.Creating" :label="t('initialPassword')">
          <ElInput
            v-model="editingUser.initialPassword"
            type="password"
            show-password
          />
        </ElFormItem>
      </ElForm>
      <template #footer>
        <ElButton @click="isEditDialogShown = false">{{t('cancel')}}</ElButton>
        <ElButton
          :loading="isEditionSubmitting"
          type="primary"
          @click="onSubmitUser(editUserFormRef)"
        >
          {{t('submit')}}
        </ElButton>
      </template>
    </ElDialog>
  </SubViewContainer>
</template>

<i18n lang="yaml" locale="zh-CN">
  id: 'ID'
  userName: '用户名'
  authRoles: '角色'
  createdAt: '创建时间'
  operations: '操作'
  createUser: '新增用户'
  edit: '编辑'
  authRole: '授权'
  resetPassword: '重置密码'
  delete: '删除'
  dialogTitle:
    creating: '新增用户'
    editing: '编辑用户'
    resetPassword: '重置密码'
  inputUserNamePlease: '请输入用户名'
  sureToDelete: '你确定要删除用户“{userName}”吗？'
  selectRolesPlease: '请选择用户角色'
  initialPassword: '初始密码'
  newPassword: '新密码'
  inputPasswordPlease: '请输入新密码'
  cancel: '取消'
  submit: '提交'
  datetimeFormatter: 'YYYY-MM-DD HH:mm:ss'
</i18n>

<style lang="scss" scoped>
.divider {
  margin: 0 12px;
}

.pagination-container {
  display: flex;
  flex-direction: row;
  justify-content: flex-end;
  width: 100%;
  margin-top: 20px;
}

.edit-user-form {
  padding: 0 12px;
}

.roles-selector {
  width: 100%;
}
</style>
